Уведомления

Группа в Telegram: @pythonsu

#1 Май 14, 2012 17:53:07

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

lambdify функция с условием

Некоторая функция w конструируется путем дифференцирования (как она выглядит не нужно знать, но пользоваться этой функцией нужно). Известно что при условии модуль (t-u) > epsilon функцией можно пользоваться, при модуль (t-u) > epsilon — нет. Как бы передать это условие в “конструктор” функции ? В примере ниже, результат правильный, но тратится время на бесполезное деление на ноль и вылетает предупреждение.

$ cat  ttest.py 
#!/usr/bin/python
import sympy
import numpy
x,y=sympy.symbols('x y')
f=1/(x-y)
v=sympy.diff(f,x)
w=sympy.lambdify((x,y),v)
t=numpy.array([1,2,3,4,5]).reshape(-1,1)
u=numpy.array([1,3]).reshape(1,-1)
plusIndex=numpy.abs(t-u)>0.00001
R=numpy.ones((5,2),dtype='d')
R[plusIndex]=w(t,u)[plusIndex]
print R


$ ./ttest.py
Warning: divide by zero encountered in true_divide
[[ 1. -0.25 ]
[-1. -1. ]
[-0.25 1. ]
[-0.11111111 -1. ]
[-0.0625 -0.25 ]]



Отредактировано dd67 (Май 14, 2012 17:57:55)

Офлайн

#2 Май 14, 2012 18:20:14

fata1ex
От:
Зарегистрирован: 2009-07-11
Сообщения: 732
Репутация: +  52  -
Профиль   Отправить e-mail  

lambdify функция с условием

Не очень понятна проблема. Почему нельзя использовать обычное ветвление с if?

Кажется, я понял вас, оберните в декоратор функцию. Если очень грубо:

>>> def bar(func):
...     def inner(a, b):
...         if b != 0:
...             return func(a,b)
...             
...     return inner
...     
>>> @bar
... def foo(a, b):
...     return a / b
...     
>>> foo(1, 2.0)
0.5
>>> foo(1, 0)
>>>



Отредактировано fata1ex (Май 14, 2012 18:43:20)

Офлайн

#3 Май 14, 2012 19:01:46

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

lambdify функция с условием

fata1ex
Кажется, я понял вас, оберните в декоратор функцию.

проблема в том, что мне нужно работать с массивом numpy.array. И в этом массиве игнорировать расчет некоторых элементов. И нужно как-то сказать lambdify функции: “не считать такие-то элементы”, т.е. сделать как-то так
w=sympy.lambdify((x,y), v if sympy.abs(x-y)>0.001 else 0.0 , modules='numpy')
но в этом коде, как я понимаю, проблема вот в чем : v - может быть числом, может быть вектором, а может быть матрицей.

А мне нужно указать, что не нужно считать какой-то конкретный элемент из всей матрицы, не прибегая к циклам.



Офлайн

#4 Май 14, 2012 19:06:29

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

lambdify функция с условием

fata1ex
Не очень понятна проблема.

Я не знаю как выглядит функция (сейчас в примере функция простая). Но я могу вычислить индексы выражения, в которых функцию нельзя считать (в проблемных местах будет использована другая функция). Сейчас не использую положительные индексы plusIndex:
$ cat ttest.py 
#!/usr/bin/python
import sympy
import numpy
x,y=sympy.symbols('x y')
f=1/(x-y)
v=sympy.diff(f,x)
sympy.pprint(v)
w=sympy.lambdify((x,y), v, modules='numpy')
t=numpy.array([1,2,3,4,5]).reshape(-1,1)
u=numpy.array([1,3]).reshape(1,-1)
plusIndex=numpy.abs(t-u)>0.00001
R=numpy.ones((5,2),dtype='d')
R=w(t,u)
print R


$ ./ttest.py
-1
────────
2
(x - y)
Warning: divide by zero encountered in true_divide
[[ -inf -0.25 ]
[-1. -1. ]
[-0.25 -inf]
[-0.11111111 -1. ]
[-0.0625 -0.25 ]]

в этом простом примере inf заменить не проблема, но в большой матрице не хочется на вычисление inf и nan тратить время + нехочется наблюдать Warning (а может и Error в более сложных случаях).



Отредактировано dd67 (Май 14, 2012 19:08:26)

Офлайн

#5 Май 14, 2012 19:16:29

fata1ex
От:
Зарегистрирован: 2009-07-11
Сообщения: 732
Репутация: +  52  -
Профиль   Отправить e-mail  

lambdify функция с условием

Почему вы не можете просто пробежаться по всем парам элементов (с помощью filter или генератора) и вызывать проблемную функцию только для подходящих пар. Делать это можно как в декораторе, так и явно.



Офлайн

#6 Май 14, 2012 19:31:52

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

lambdify функция с условием

fata1ex
Почему вы не можете просто пробежаться по всем парам элементов (с помощью filter или генератора) и вызывать проблемную функцию только для подходящих пар. Делать это можно как в декораторе, так и явно.

борюсь за скорость.



Офлайн

#7 Май 14, 2012 19:38:55

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

lambdify функция с условием

мне нужно решить задачу средствами нумпай, питоновские циклы сильно медленные.

используя http://docs.scipy.org/doc/numpy/reference/routines.html и пытаюсь что-то сделать, но с подходящими функциями возникают какие-то проблемы, например

RR=numpy.frompyfunc(w, plusIndex, plusIndex)
print RR

Traceback (most recent call last):
File "./ttest.py", line 17, in <module>
RR=numpy.frompyfunc(w, plusIndex, plusIndex)
TypeError: only length-1 arrays can be converted to Python scalars

функция w получат вектора строки и столбцы и должна возвратить матрицу



Отредактировано dd67 (Май 14, 2012 19:40:59)

Офлайн

#8 Май 14, 2012 19:46:32

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

lambdify функция с условием

Получилось !

надеюсь по времени не сильно тормозит ….

def functW(_t_,_u_):
if _t_ != _u_: return w(_t_,_u_)
else: return 0.0
W=numpy.vectorize(functW)
print W(t,u)



Офлайн

Board footer

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

Powered by DjangoBB

Lo-Fi Version