Уведомления

Группа в Telegram: @pythonsu

#1 Июнь 21, 2012 12:00:28

dd67
От:
Зарегистрирован: 2011-12-22
Сообщения: 35
Репутация: +  1  -
Профиль   Отправить e-mail  

передать функцию как параметр в vectorize

Имеется много символических функций (например, 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)



Офлайн

#2 Июнь 21, 2012 13:04:33

FishHook
От:
Зарегистрирован: 2011-01-08
Сообщения: 8312
Репутация: +  568  -
Профиль   Отправить e-mail  

передать функцию как параметр в vectorize

Думаю, как то так

# -*- 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])



Офлайн

#3 Июнь 22, 2012 23:20:10

dd67
От:
Зарегистрирован: 2011-12-22
Сообщения: 35
Репутация: +  1  -
Профиль   Отправить e-mail  

передать функцию как параметр в vectorize

Можно ли как-то оптимизировать функцию 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 (Июнь 22, 2012 23:23:27)

Офлайн

#4 Июнь 24, 2012 16:05:47

dd67
От:
Зарегистрирован: 2011-12-22
Сообщения: 35
Репутация: +  1  -
Профиль   Отправить e-mail  

передать функцию как параметр в vectorize

код без векторизаии поэлементной функции работает гораздо быстрее (т.к. 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



Отредактировано dd67 (Июнь 24, 2012 16:13:54)

Офлайн

Board footer

Модераторировать

Powered by DjangoBB

Lo-Fi Version