Найти - Пользователи
Полная версия: передать функцию как параметр в vectorize
Начало » Python для новичков » передать функцию как параметр в vectorize
1
dd67
Имеется много символических функций (например, F и G в примере ниже), которые нельзя вычислять при x=y. Эти функции нужно преобразовать в numpy функции и векторизовать. Исключение случая x=y можно сделать одной функцией withoutZero.

Помогите одолеть синтаксис.
$ cat ttest.py 
#!/usr/bin/python
import numpy 
import sympy
x,y=sympy.symbols('x y')
F=1/(x-y)**2
G=1/(x-y)
def withoutZero(x,y,sFunct=0):
    if numpy.abs(x-y)>0.00001: 
        return sympy.lambdify((x,y),sFunct,modules='numpy')(x,y) 
    else: return 0.0
KF=numpy.vectorize(withoutZero(x,y,F))
KG=numpy.vectorize(withoutZero(x,y,G))
print KF(1,2)
$ ./ttest.py 
Traceback (most recent call last):
  File "./ttest.py", line 13, in <module>
    print KF(1,2)
  File "/usr/lib/pymodules/python2.7/numpy/lib/function_base.py", line 1813, in __call__
    theout = self.thefunc(*newargs)
TypeError: __call__() takes exactly 2 arguments (3 given)
FishHook
Думаю, как то так
# -*- coding:utf-8 -*-
import numpy 
import sympy
x,y=sympy.symbols('x y')
F=1/(x-y)**2
G=1/(x-y)
def withoutZero(sFunct=None):
    def lmbd(i,j):
        if numpy.abs(i-j)>0.00001: 
            return sympy.lambdify((x,y),sFunct,modules='numpy')(i,j)
        else: return 0.0
        
    return lmbd
    
KF=numpy.vectorize(withoutZero(sFunct=F))
KG=numpy.vectorize(withoutZero(sFunct=G))
print KF([1,2,4,5,6, 7],[2,4,5,6,4,3])
print KG([1,2,4,5,6, 7],[2,4,5,6,4,3])
dd67
Можно ли как-то оптимизировать функцию withoutZero, таким образом, чтобы она быстрее работала c numpy-массивами?

Эту функцию требуется вызывать для больших numpy-массивов, например:
x,y=sympy.symbols('x y')
G=1/(x-y)+sympy.log(sympy.abs(x-y))
F=sympy.diff(G,x)
sympy.pprint(F)
def withoutZero(sFunct=None,eps=0.0001):
    def lmbd(a,b):
        if numpy.abs(a-b)>eps: 
            return sympy.lambdify((x,y),sFunct,modules='numpy')(a,b) 
        else: return 0.0
    return numpy.vectorize(lmbd)
KF=withoutZero(sFunct=F)
n=1000
t=numpy.ones(n)
u=2.*numpy.ones(n)
print KF(t,u)

Причем numpy-массивы будут содержать только вещественные числа.

dd67
код без векторизаии поэлементной функции работает гораздо быстрее (т.к. vectorize, даже с otypes= работает очень медленно). Можно ли в коде ниже избавиться от расчетов элементов с делением на ноль, если их индексы известны (на месте таких элеметов д.б. ноль)?

#!/usr/bin/python
import numpy 
import sympy
x,y=sympy.symbols('x y')
G=1/(x-y)+sympy.log(sympy.abs(x-y))
F=sympy.diff(G,x)
sympy.pprint(F)
def lmbdFun(sFunct=None):
    return sympy.lambdify((x,y),sFunct,modules='numpy') 
KF=lmbdFun(sFunct=F)
t=numpy.array([1,2,3,4,5])
u=numpy.array([1,3,3,5,5])
res=numpy.zeros(5)
good=(t!=u)
res[good]=KF(t,u)[good]
print res

$ ./ttest.py 
re(x - y) 1
───────── - ────────
2 2
│x - y│ (x - y)
Warning: invalid value encountered in true_divide
Warning: divide by zero encountered in true_divide
[ 0. -2. 0. -2. 0.]

p.S. это код считает все верно, но хочется избавится об бессмысленных вычислений с делением на ноль.


некрасиво, но работает
$ cat ./ttest.py 
#!/usr/bin/python
import numpy 
import sympy
x,y=sympy.symbols('x y')
G=1/(x-y)+sympy.log(sympy.abs(x-y))
F=sympy.diff(G,x)
sympy.pprint(F)
def lmbdFun(sFunct=None):
    return sympy.lambdify((x,y),sFunct,modules='numpy') 
KF=lmbdFun(sFunct=F)
t=numpy.array([1,2,3,4,5])
u=numpy.array([1,3,3,5,5])
res=numpy.zeros(5)
good=(t!=u)
bad=(t==u)
t[bad]=u[bad]+1
res[good]=KF(t,u)[good]
print res
This is a "lo-fi" version of our main content. To view the full version with more information, formatting and images, please click here.
Powered by DjangoBB